package com.yy.smartBI.controller;


/**
 * 图表接口
 */

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yy.api.AIServiceClient;
import com.yy.smartBI.common.BaseResponse;
import com.yy.smartBI.exception.ThrowUtils;
import com.yy.smartBI.mapper.GenChartMapper;
import com.yy.smartBI.model.dto.chart.UploadExcelToCsvRequest;
import com.yy.smartBI.model.entity.GenChart;
import com.yy.smartBI.model.entity.User;
import com.yy.smartBI.model.enums.ChartTypeEnum;
import com.yy.smartBI.model.enums.FileUploadBizEnum;
import com.yy.smartBI.model.vo.ChartVO;
import com.yy.smartBI.service.ChartService;
import com.yy.smartBI.service.GenChartService;
import com.yy.smartBI.utils.AIUtils;
import com.yy.smartBI.utils.ExcelUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

import static com.yy.smartBI.constant.UserConstant.USER_LOGIN_STATE;

@RestController
@RequestMapping("/chart")
@RequiredArgsConstructor
@Slf4j
public class ChartContoller {
    @Resource
    private GenChartMapper genChartMapper;
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Resource
    private ChartService chartService;

    private final AIServiceClient aiServiceClient;

    @PostMapping("/upload/excel")
    public BaseResponse<ChartVO> uploadExcelToChart(@RequestPart("file") MultipartFile file, UploadExcelToCsvRequest uploadExcelToCsvRequest, HttpServletRequest request) throws IOException {
        //1.校验参数
        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartType()), new IllegalArgumentException("图表类型不能为空"));
//        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartName()),new IllegalArgumentException("图表名称不能为空"));
        ThrowUtils.throwIf(file == null, new IllegalArgumentException("文件不能为空"));
        String chartType = uploadExcelToCsvRequest.getChartType();
        if (!ChartTypeEnum.getValues().contains(chartType)) {
            log.error("图表类型参数错误");
            throw new IllegalArgumentException("图表类型错误");
        }
        //文件类型校验
        String originalFilename = file.getOriginalFilename();
        String contentType = file.getContentType();
        String suffix = FileUtil.getSuffix(originalFilename);
        //定义合法的文件后缀类型
        List<String> whiteFileSuffixList = Arrays.asList("xlsx", "xls");
        ThrowUtils.throwIf(!whiteFileSuffixList.contains(suffix), new IllegalArgumentException("文件类型错误"));
        //文件大小校验
        long size = file.getSize();
        if (size > 1024 * 1024) {
            log.error("文件大小超出限制");
            throw new IllegalArgumentException("文件大小超出限制");
        }
        //2.使用EasyExcel读文件
        String data;
        try {
            data = ExcelUtils.excelToCsv(file);
        } catch (Exception e) {
            log.error("excel 转 csv 失败", e);
            return new BaseResponse<>(-1, null, "转换失败");
        }
        if (StrUtil.isBlank(data)) {
            log.error("excel 转 csv 无结果");
            return new BaseResponse<>(-1, null, "转换失败");
        }
        //todo  拆分 3. 调用大模型
        String question = uploadExcelToCsvRequest.getChartType() + data;
        String answer = aiServiceClient.getAnswer(question);
//        String answer = AIUtils.getAnswer(question);
        //4.分离建议和代码
        String[] split = answer.split("]]]]]");
        ChartVO chartVO = new ChartVO();
        try {
            chartVO.setCode(split[1]);
            chartVO.setAdvice(split[2]);
            chartVO.setChartType(chartType);
        } catch (ArrayIndexOutOfBoundsException e) {
            log.error("AI 回答格式不对 无法获取结果", e);
            return new BaseResponse<>(-1, null, "转换失败");
        }
        //4.返
        return new BaseResponse<>(0, chartVO, "转换成功");
    }


    @PostMapping("/upload/excel/asyn/test")
    public BaseResponse uploadExcelToChartsAsyn(@RequestPart("file") MultipartFile file, UploadExcelToCsvRequest uploadExcelToCsvRequest, HttpServletRequest request) throws IOException {
        //1.校验参数
        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartType()), new IllegalArgumentException("图表类型不能为空"));
//        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartName()),new IllegalArgumentException("图表名称不能为空"));
        ThrowUtils.throwIf(file == null, new IllegalArgumentException("文件不能为空"));
        String chartType = uploadExcelToCsvRequest.getChartType();
        if (!ChartTypeEnum.getValues().contains(chartType)) {
            log.error("图表类型参数错误");
            throw new IllegalArgumentException("图表类型错误");
        }
        //文件类型校验
        String originalFilename = file.getOriginalFilename();
        String contentType = file.getContentType();
        String suffix = FileUtil.getSuffix(originalFilename);
        //定义合法的文件后缀类型
        List<String> whiteFileSuffixList = Arrays.asList("xlsx", "xls");
        ThrowUtils.throwIf(!whiteFileSuffixList.contains(suffix), new IllegalArgumentException("文件类型错误"));
        //文件大小校验
        long size = file.getSize();
        if (size > 1024 * 1024) {
            log.error("文件大小超出限制");
            throw new IllegalArgumentException("文件大小超出限制");
        }
        //2.使用EasyExcel读文件
        String data;
        try {
            data = ExcelUtils.excelToCsv(file);
        } catch (Exception e) {
            log.error("excel 转 csv 失败", e);
            return new BaseResponse<>(-1, null, "转换失败");
        }
        if (StrUtil.isBlank(data)) {
            log.error("excel 转 csv 无结果");
            return new BaseResponse<>(-1, null, "转换失败");
        }
        //3.调用大模型
        String question = uploadExcelToCsvRequest.getChartType() + data;
        //创建图表
        GenChart chart = new GenChart();
        chart.setChartType(chartType);
        User currentUser = (User) request.getSession().getAttribute(USER_LOGIN_STATE);
        if (currentUser != null) {
            chart.setUserId(currentUser.getId());
        }
        chart.setStatus("wait");
        //异步调用
        CompletableFuture.runAsync(() -> {
            //1.先保存任务到数据库
            int insert = genChartMapper.insert(chart);
            QueryWrapper<GenChart> genChartQueryWrapper = new QueryWrapper<>();
            genChartQueryWrapper.eq("id", chart.getId());
            if (insert < 1) {
                log.error("数据库执行出错 创建图表失败");
                throw new IllegalArgumentException("数据库执行出错 创建图表失败");
            }
            //2.调用大模型
            String answer = AIUtils.getAnswer(question);
            String[] split = answer.split("]]]]]");
            if (split.length < 3) {
                log.error("AI 回答格式不对 无法获取结果");
                chart.setStatus("fail");
                genChartMapper.update(chart, genChartQueryWrapper);
                throw new IllegalArgumentException("AI 回答格式不对 无法获取结果");
            }
            chart.setCode(split[1]);
            chart.setAdvice(split[2]);
            chart.setStatus("success");
            //3.更新数据库
            int update = genChartMapper.update(chart, genChartQueryWrapper);
            if (update < 1) {
                log.error("数据库执行出错 更新图表失败");
                throw new IllegalArgumentException("数据库执行出错 更新图表失败");
            }
        }, threadPoolExecutor);
        //4.分离建议和代码
        return new BaseResponse<>(0, "转换成功");
    }


    @PostMapping("/upload/excel/asyn")
    public BaseResponse uploadExcelToChartsAsynMQ(@RequestPart("file") MultipartFile file, UploadExcelToCsvRequest uploadExcelToCsvRequest, HttpServletRequest request) throws IOException {
        //1.校验参数
        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartType()), new IllegalArgumentException("图表类型不能为空"));
//        ThrowUtils.throwIf(StrUtil.isBlank(uploadExcelToCsvRequest.getChartName()),new IllegalArgumentException("图表名称不能为空"));
        ThrowUtils.throwIf(file == null, new IllegalArgumentException("文件不能为空"));
        String chartType = uploadExcelToCsvRequest.getChartType();
        if (!ChartTypeEnum.getValues().contains(chartType)) {
            log.error("图表类型参数错误");
            throw new IllegalArgumentException("图表类型错误");
        }
        //文件类型校验
        String originalFilename = file.getOriginalFilename();
        String contentType = file.getContentType();
        String suffix = FileUtil.getSuffix(originalFilename);
        //定义合法的文件后缀类型
        List<String> whiteFileSuffixList = Arrays.asList("xlsx", "xls");
        ThrowUtils.throwIf(!whiteFileSuffixList.contains(suffix), new IllegalArgumentException("文件类型错误"));
        //文件大小校验
        long size = file.getSize();
        if (size > 1024 * 1024) {
            log.error("文件大小超出限制");
            throw new IllegalArgumentException("文件大小超出限制");
        }
        //调用模型 处理
        boolean result = chartService.uploadExcelToChartsAsynMQ(file, uploadExcelToCsvRequest, request);
        return new BaseResponse<>(0, "转换成功");
    }
}
